#include "device_manage.h"

#include <stdlib.h>

#include <ctimer.h>
#include <etimer.h>
#include <process.h>
#include "disp_task.h"
#include "lib/list.h"
#include "lora_task.h"
#include "memb.h"

#include <string.h>
#include "74hc595.h"
#include "fifo.h"
#include "fun_flash.h"
#include "key_task.h"
#include "stm32f1xx_hal.h"
#include "time.h"
#include "uart.h"
#include "voice_task.h"

#include "radio.h"
#include "sx1276-LoRa.h"
#include "sx1276.h"
#include "sx1278-Hal.h"

tRadioDriver *Radio = NULL;

uint8_t Buffer[128];
uint8_t BufferSize;

LIST(callnum_list);  //呼叫号码列表
LIST(callmac_list);  //呼叫地址列表
LIST(sendmac_list);  //发送呼叫地址列表

extern uint8_t led;

tSend_Data send_data;  // lora发送数据

uint8_t senddata_buff[64];  //发送数据buff
uint8_t senddata_len;       //发送数据长度
uint8_t resend_len;
uint8_t resend_cnt;
bool is_exist = false;    //分机是否存在
uint8_t device_type = 0;  //分机设备类型

uint16_t num_Cur = 0;  //

uint8_t mac[12] = {0};

PROCESS(LORA_Process, "LORA");          // LORA任务
PROCESS(LORASend_Process, "LORASend");  //发送任务
PROCESS(Reset_Process, "Reset");        //重启任务

struct ctimer c_resend;      //重发定时器
struct ctimer c_macsave;     // mac缓存定时器
struct ctimer c_qrcodesave;  //二维码绑定定时器
struct ctimer c_sendmac;     //发送定时器

uint8_t sendmac_timer_flag = 0;

iSMacSn SalveMac;  //呼叫器mac

MEMB(m_mac, tMacCall, 64);
MEMB(m_num, tListNum, 32);

/**
 * @brief  呼叫分机地址缓存内存初始化
 * @note   使用MEMB创建list
 * @retval None
 */
void memb_maccall_init(void) { memb_init(&m_mac); }
/**
 * @brief  显示号码缓存初始化
 * @note   使用MEMB创建list
 * @retval None
 */
void memb_numcall_init(void) { memb_init(&m_num); }

/**
 * @brief  呼叫分机地址缓存内存申请
 * @note
 * @retval 申请的内存
 */
tMacCall *memb_maccall_alloc(void) {
  tMacCall *mac_call = (tMacCall *)memb_alloc(&m_mac);
  return mac_call;
}

/**
 * @brief  显示号码内存申请
 * @note
 * @retval 申请的内存
 */
tListNum *memb_numcall_alloc(void) {
  tListNum *num_call = (tListNum *)memb_alloc(&m_num);
  return num_call;
}

/**
 * @brief  呼叫分机缓存内存释放
 * @note
 * @param  *ptr: 呼叫分机缓存
 * @retval None
 */
void memb_maccall_free(void *ptr) { memb_free(&m_mac, ptr); }

/**
 * @brief 显示号码内存释放
 * @note
 * @param  *ptr: 显示号码内存
 * @retval None
 */
void memb_numcall_free(void *ptr) { memb_free(&m_num, ptr); }

void menb_num_debug(char *fun) {
  printf("%s m_num mem -> %d,list_len->%d\r\n", fun, memb_numfree(&m_num),
         get_callnum_cnt());
}

void **get_callnum_list() { return callnum_list; }

/**
 * @brief  显示添加分机号码
 * @note
 * @param  add_num: 添加的分机号
 * @retval None
 */
void disp_addnum(uint16_t add_num) {
  static sLEDData set_data;

  set_data.cmd = disp_notwinkle;  //添加成功，常亮显示
  set_data.count = 3;
  set_data.index = 0;
  //常亮显示完成后，继续闪烁添加分机模式
  set_data.timeout_handle = enter_addnum;
  set_data.led[0] = 0x00;
  set_data.led[1] = NumDis[add_num % 1000 / 100];
  set_data.led[2] = NumDis[add_num % 100 / 10];
  set_data.led[3] = NumDis[add_num % 10 / 1];
  set_data.led[4] = 0x00;

  process_post(&Disp_Process, PROCESS_EVENT_MSG, (process_data_t)&set_data);
}

/**
 * @brief  获取呼叫号码的数量
 * @note
 * @retval 呼叫号码数量
 */
uint8_t get_callnum_cnt(void) { return list_length(callnum_list); }

/**
 * @brief 获取定位呼叫分机的数量
 * @note
 * @retval
 */
uint8_t get_callmac_cnt(void) { return list_length(callmac_list); }

/**
 * @brief  发送Mac数量
 * @note
 * @retval
 */
uint8_t get_sendmac_cnt(void) { return list_length(sendmac_list); }

/**
 * @brief 从列表中获取第一个呼叫号码
 * @note
 * @retval None
 */
void *get_cur_num(void) { return list_pop(callnum_list); }

/**
 * @brief  从列表中获取第最后一个呼叫号码
 * @note
 * @retval None
 */
void *get_last_num(void) { return list_chop(callnum_list); }

/**
 * @brief  查找并获取呼叫Mac
 * @note
 * @param  mac:
 * @param  **maccall:
 * @retval
 */
uint8_t get_find_mac(iSMacSn mac, tMacCall **maccall) {
  tMacCall *mac_call;

  for (mac_call = list_head(callmac_list); mac_call != NULL;
       mac_call = mac_call->next) {
    if (mac_call->mac.temp0 == mac.temp0 && mac_call->mac.temp1 == mac.temp1 &&
        mac_call->mac.temp2 == mac.temp2) {
      *maccall = mac_call;
      return 1;
    }
  }
  return 0;
}

/**
 * @brief  查找发送Mac
 * @note
 * @param  mac:
 * @retval
 */
uint8_t find_sendmac(iSMacSn mac) {
  tMacCall *mac_call;

  for (mac_call = list_head(sendmac_list); mac_call != NULL;
       mac_call = mac_call->next) {
    if (mac_call->mac.temp0 == mac.temp0 && mac_call->mac.temp1 == mac.temp1 &&
        mac_call->mac.temp2 == mac.temp2) {
      return 1;
    }
  }
  return 0;
}

void add_sendmac(iSMacSn mac) {
  tMacCall *maccall = (tMacCall *)memb_maccall_alloc();
  maccall->mac = SalveMac;
  maccall->timeout = 4;
  list_add(sendmac_list, maccall);
}

/**
 * @brief  添加呼叫号码到list
 * @note  在list后添加
 * @param  *item: 呼叫信息
 * @retval None
 */
void set_cur_num(void *item) { list_add(callnum_list, item); }
/**
 * @brief  添加呼叫号码到list
 * @note  在list前添加
 * @param  *item: 呼叫信息
 * @retval None
 */
void set_curf_num(void *item) { list_push(callnum_list, item); }

/**
 * @brief  添加呼叫分机信息到list
 * @note   先缓存呼叫信息，用于匹配定位信息
 * @param  *item:
 * @retval None
 */
void set_cur_mac(void *item) { list_add(callmac_list, item); }

/**
 * @brief  从呼叫list里面移除
 * @note
 * @param  *item:
 * @retval None
 */
void remove_num(void *item) { list_remove(callnum_list, item); }

/**
 * @brief  删除指定呼叫号码
 * @note
 * @param  num: 显示号码
 * @retval None
 */
uint8_t remove_callnum(uint16_t num) {
  tListNum *listnum;

  for (listnum = list_head(callnum_list); listnum != NULL;
       listnum = listnum->next) {
    if (listnum->slave.Val == num) {
      list_remove(callnum_list, listnum);
      memb_numcall_free(listnum);
      return 1;
    }
  }
  return 0;
}

/**
 * @brief  删除所有呼叫号码
 * @note
 * @retval None
 */
void remove_callnum_all(void) {
  tListNum *listnum;
  while (get_callmac_cnt() > 0) {
    for (listnum = list_head(callnum_list); listnum != NULL;
         listnum = listnum->next) {
      list_remove(callnum_list, listnum);
      memb_numcall_free(listnum);
    }
  }
}

void disp_callnum() {
  static sLEDData set_data;
  tListNum *num;

  bool isadd = false;

  uint16_t curnum = get_curflash_num();
  for (num = list_head(callnum_list); num != NULL; num = num->next) {
    if (num->slave.Val == curnum) {
      isadd = true;
      break;
    }
  }

  if (find_dispnum(curnum) == 1) {
    isadd = true;
  }

  if (!isadd) {  //显示队列不存在该号码
    tListNum *cur_listnum = (tListNum *)memb_numcall_alloc();

    cur_listnum->slave.Val = curnum;            //显示提醒号码
    cur_listnum->cnt = cfg_data.Val.RemindCnt;  //提醒次数
    cur_listnum->time = 5;                      //显示时间 秒
    cur_listnum->is_disp = 0;                   //标志为未播放
    if (list_length(callnum_list) == 0) {
      set_data.cmd = disp_num;
      set_data.count = 1;
      process_post(&Disp_Process, PROCESS_EVENT_MSG, (process_data_t)&set_data);
    }
    list_add(callnum_list, cur_listnum);  //添加到list
    led = Led_Call;
    process_start(&DispLed_Process, (process_data_t)&led);
  }
}

void disp_delnum() {
  static sLEDData set_data;
  uint16_t curnum = get_curflash_num();
  set_data.cmd = disp_notwinkle;  //添加成功，常亮显示
  set_data.count = 30;
  set_data.index = 0;
  set_data.timeout_handle = NULL;  //常亮显示完成后，继续闪烁添加分机模式
  set_data.led[0] = 0x00;
  set_data.led[1] = NumDis[curnum % 1000 / 100];
  set_data.led[2] = NumDis[curnum % 100 / 10];
  set_data.led[3] = NumDis[curnum % 10 / 1];
  set_data.led[4] = 0x00;
  process_post(&Disp_Process, PROCESS_EVENT_MSG, (process_data_t)&set_data);
}

/**
 * @brief  lora通讯异或检验
 * @note
 * @param  *data: 数据
 * @param  length: 长度
 * @retval 校验值
 */
static uint8_t checkxor(uint8_t *data, uint16_t length) {
  uint8_t x_or = data[0];
  uint8_t *head = data;
  for (uint16_t i = 1; i < length; i++) {
    x_or ^= *++head;
  }
  return x_or;
}

/**
 * @brief  lora发送拼包函数
 * @note
 * @param  device: 设备类型
 * @param  salve: 分机Mac
 * @param  cmd: 命令
 * @param  *data: 数据
 * @param  len: 数据长度
 * @retval None
 */
void lora_send(uint8_t device, iSMacSn salve, uint8_t cmd, uint8_t *data,
               uint8_t len) {
  uint8_t index = 0;
  uSMacSn Sn;

  if (resend_cnt > 0) {
    return;
  }
  Sn.Mac.temp0 = salve.temp0;
  Sn.Mac.temp1 = salve.temp1;
  Sn.Mac.temp2 = salve.temp2;
  senddata_buff[index++] = Lora_Head;
  senddata_buff[index++] = device;

  if ((device == device_ble) || (device == device_cfg) || (device == device_ble_no)) {
    for (uint8_t i = 6; i < 12; i++) {
      senddata_buff[index++] = Sn.Mac_Var[i];
    }
  } else {
    for (uint8_t i = 0; i < 12; i++) {
      senddata_buff[index++] = Sn.Mac_Var[i];
    }
  }
  senddata_buff[index++] = cmd | Lora_Cmd_Mask;
  senddata_buff[index++] = len;
  for (uint8_t i = 0; i < len; i++) {
    senddata_buff[index++] = data[i];
  }
  uint8_t crc = checkxor(&senddata_buff[1], index - 1);
  senddata_buff[index++] = crc;
  senddata_len = index;
  resend_len = senddata_len;
#if (0)
  printf("senddata_buff:");
  for (uint8_t i = 0; i < index; i++) {
    printf("%02X", senddata_buff[i]);
  }
#endif
  process_start(&LORASend_Process, NULL);
}

void package2mqtt(uint8_t device_type, iSMacSn SalveMac, uint8_t cmd,
                  uint8_t power, Location *location) {
  if (device_type == device_ble || device_type==device_ble_no) {
    if (cmd == call_cmd_call) {
      PackageST package;
      package.mac = SalveMac;
      package.power = power;
      send_callnum(package);
    } else {
      PackageBLE package;
      package.mac = SalveMac;
      package.power = power;
      memcpy(package.location.mac, location->mac, 6);
      send_callnum_location(package);
    }
  } else {
    PackageST package;
    package.mac = SalveMac;
    package.power = power;
    send_callnum(package);
  }
}

/**
 * @brief  lora重发定时器回调函数
 * @note
 * @param  *parm:传入参数
 * @retval None
 */
void resend_callback(void *parm) {
  senddata_len = resend_len;
  if (resend_cnt == 10) {
    ctimer_stop(&c_resend);
    resend_cnt = 0;
  } else {
    ctimer_reset(&c_resend);
    resend_cnt++;
  }
  process_start(&LORASend_Process, NULL);
}

/**
 * @brief  分机呼叫mac缓存超时定时器回调函数
 * @note
 * @param  *parm: 传入参数
 * @retval None
 */
void mactimeout_callback(void *parm) {
  static tMacCall *mac_call;

  for (mac_call = list_head(callmac_list); mac_call != NULL;
       mac_call = mac_call->next) {
    if (mac_call->timeout == 0) {
      uint8_t cmd = call_cmd_call;
      package2mqtt(device_ble, mac_call->mac, cmd, mac_call->power, NULL);
      list_remove(callmac_list, mac_call);  //从list中移除
      memb_maccall_free(mac_call);          //释放内存
    } else {
      mac_call->timeout--;
    }
  }
  if (get_callmac_cnt() > 0) {
    ctimer_reset(&c_macsave);
  } else {
    ctimer_stop(&c_macsave);
  }
}

/**
 * @brief  保存二维码超时
 * @note
 * @param  *parm:
 * @retval None
 */
void qrcodesave_callback(void *parm) {
  write_cfg(&cfg_data);
  ctimer_stop(&c_resend);
  resend_cnt = 0;
  ctimer_stop(&c_qrcodesave);
  process_start(&Reset_Process, NULL);
}

/**
 * @brief
 * @note
 * @param  *parm:
 * @retval None
 */
void sendmqtt_timeout_callback(void *parm) {
  static tMacCall *mac_call;

  for (mac_call = list_head(sendmac_list); mac_call != NULL;
       mac_call = mac_call->next) {
    if (mac_call->timeout == 0) {
      list_remove(sendmac_list, mac_call);  //从list中移除
      memb_maccall_free(mac_call);          //释放内存
    } else {
      mac_call->timeout--;
    }
  }
  if (get_sendmac_cnt() > 0) {
    ctimer_reset(&c_sendmac);
  } else {
    ctimer_stop(&c_sendmac);
    sendmac_timer_flag = 0;
  }
}

void start_sendmac_timer(void) {
  if (sendmac_timer_flag == 0) {
    ctimer_set(&c_sendmac, 1 * 1000, sendmqtt_timeout_callback, NULL);
    sendmac_timer_flag = 1;
  }
}

/**
 * @brief  呼叫处理模式
 * @note
 * @param  device_type: 设备类型
 * @param  SalveMac: 分机Mac
 * @param  *data: 分机呼叫数据
 * @param  len: 呼叫数据长度
 * @retval None
 */
void model_call_process(uint8_t device_type, iSMacSn SalveMac, uint8_t *data,
                        uint8_t len) {
  static uint8_t lora_cmd = lora_cmd_call_master;
  uint8_t res_data;

  if (!is_exist) {
    if (/*riss > -85.00*/ 1) {
	  uint8_t cmd = data[0];
      if (netdevice_type != net_device_none ||
        cfg_data.Val.AddFlag == HaveAdd) {
        if (find_sendmac(SalveMac) == 0) {
           uint8_t power = 0;
		  if(cmd == call_cmd_call){
		    power = data[1];
		  }
          PackageST package;
          package.mac = SalveMac;
          package.power = power;
          send_register(package);
          package.mac = SalveMac;
          add_sendmac(SalveMac);
          start_sendmac_timer();
        }
      }
	  printf("lora register\r\n");
	  if(cmd == call_cmd_call || cmd == call_cmd_location){
		res_data = call_cmd_resp_none;  //回应lora命令
		lora_send(device_type, SalveMac, lora_cmd, &res_data, 1);
	  }
    }
    return;
  }

  if (netdevice_type != net_device_none ||
      cfg_data.Val.AddFlag == HaveAdd)  //网络设备且主机已经添加
  {
    uint8_t cmd = data[0];
    if (device_type == device_ble_no) {  //非定位类型消息，收到立刻发送
      if (cmd == call_cmd_call) {
        uint8_t power = data[1];
        if (find_sendmac(SalveMac) == 0) {
          package2mqtt(device_type, SalveMac, cmd, power, NULL);
          add_sendmac(SalveMac);
          start_sendmac_timer();
        }
        res_data = call_cmd_resp_call;  //回应命令
        lora_send(device_type, SalveMac, lora_cmd, &res_data, 1);
        if ((get_menuctrl() <= ctrl_fun) ||
            (get_menuctrl() == ctrl_num)) {  //非设置模式，才显示
          disp_callnum();                    //显示呼叫号码
          enter_dispnum();
        }
		printf("device_ble_no lora call_cmd_call\r\n");
      }else if(cmd == call_cmd_cancel){
		res_data = call_cmd_resp_cancel;
		uint16_t curnum = get_curflash_num();
		bool flag1 = remove_callnum(curnum);
		bool flag2 = remove_dispnum(curnum);
	    if(flag1||flag2){
			lora_send(device_type, SalveMac, lora_cmd, &res_data, 1);
		}
		
		printf("device_ble_no lora call_cmd_cancel\r\n");
	  }
    } else {
      //定位类型，呼叫消息，收到后先存储mac到list缓存
      if (cmd == call_cmd_call) {
        tMacCall *maccall;
        uint8_t flag = get_find_mac(SalveMac, &maccall);

        if (flag == 0) {
          maccall = (tMacCall *)memb_maccall_alloc();
          maccall->mac = SalveMac;
          maccall->power = data[1];
          maccall->timeout = 8;
          set_cur_mac(maccall);
          //启动Mac缓存超时
          ctimer_set(&c_macsave, 1 * 1000, mactimeout_callback, NULL);
          if ((get_menuctrl() <= ctrl_fun) ||
              (get_menuctrl() == ctrl_num)) {  //非设置模式，才显示
            disp_callnum();                    //显示呼叫号码
            enter_dispnum();
          }
          led = Led_Call;
          process_start(&DispLed_Process, (process_data_t)&led);
        }

        res_data = call_cmd_resp_call;  //回应命令
        lora_send(device_type, SalveMac, lora_cmd, &res_data, 1);

      } else if (cmd == call_cmd_location) {
        //定位类型，位置消息，匹配Mac，发送到网络
        tMacCall *maccall;
        uint8_t flag = get_find_mac(SalveMac, &maccall);
        if (flag == 1) {
          uint8_t res = data[1];
          if (res == 1) {  //定位成功
            if (find_sendmac(SalveMac) == 0) {
              Location location;
              memcpy(location.mac, &data[2], 6);
              cmd = call_cmd_location;
              package2mqtt(device_type, SalveMac, cmd, maccall->power,
                           &location);
              add_sendmac(SalveMac);
              start_sendmac_timer();
            }
          } else {  //定位失败
            if (find_sendmac(SalveMac) == 0) {
              cmd = call_cmd_call;
              package2mqtt(device_type, SalveMac, cmd, maccall->power, NULL);
              add_sendmac(SalveMac);
              start_sendmac_timer();
            }
          }
          list_remove(callmac_list, maccall);  //从list中移除
          memb_maccall_free(maccall);          //释放内存
        } else {
          if ((get_menuctrl() <= ctrl_fun) ||
              (get_menuctrl() == ctrl_num)) {  //非设置模式，才显示
            disp_callnum();                    //显示呼叫号码
            enter_dispnum();
          }
          led = Led_Call;
          process_start(&DispLed_Process, (process_data_t)&led);
          if (find_sendmac(SalveMac) == 0) {
            Location location;
            memcpy(location.mac, &data[2], 6);
            cmd = call_cmd_location;
            package2mqtt(device_type, SalveMac, cmd, 0, &location);
            add_sendmac(SalveMac);
            start_sendmac_timer();
          }
        }

        res_data = call_cmd_resp_location;  //回应lora命令
        lora_send(device_type, SalveMac, lora_cmd, &res_data, 1);
      }else if(cmd == call_cmd_cancel){
		res_data = call_cmd_resp_cancel;
		uint16_t curnum = get_curflash_num();
		uint8_t flag1 = remove_callnum(curnum);
		uint8_t flag2 = remove_dispnum(curnum);
	    if(flag1||flag2){
			lora_send(device_type, SalveMac, lora_cmd, &res_data, 1);
		}
		printf("device_ble lora call_cmd_cancel\r\n");
	  }
    }
  }
}

/**
 * @brief  添加分机模式处理
 * @note   单机版
 * @param  device_type:分机类型
 * @param  SalveMac: 分机Mac
 * @retval None
 */
void model_add_process(uint8_t device_type, iSMacSn SalveMac) {
  static sVoiceCmd voice;
  static uint16_t voice_value;
  static uint8_t lora_cmd = lora_cmd_call_master;
  uint8_t res_data;

  if (is_exist) {
    voice_value = voice_numexist;
    voice.cmd = voicecmd_playone;
    voice.value = (uint8_t *)&voice_value;
    res_data = call_cmd_resp_call;  //回应命令
    lora_send(device_type, SalveMac, lora_cmd, &res_data, 1);
  } else {
    res_data = call_cmd_resp_add;  //回应命令
    lora_send(device_type, SalveMac, lora_cmd, &res_data, 1);

    static uint16_t add_num;
    add_num = get_addnum();
    add_flashnum(SalveMac, add_num);  //把分机添加到flash
    disp_addnum(add_num);

    led = Led_SetOk;
    process_start(&DispLed_Process, (process_data_t)&led);

    voice_value = add_num;
    voice.cmd = voicecmd_playaddnum;
    voice.value = (uint16_t *)&voice_value;
  }
  process_start(&VoicePlay_Process, (process_data_t)&voice);
}

/**
 * @brief  删除分机模式处理
 * @note   单机版
 * @param  device_type: 设备类型
 * @param  SalveMac: 分机Mac
 * @retval None
 */
void model_del_process(uint8_t device_type, iSMacSn SalveMac) {
  static sVoiceCmd voice;
  static uint16_t voice_value;
  static uint8_t lora_cmd = lora_cmd_call_master;
  uint8_t res_data;

  if (!is_exist) {
    //语音提示 不存在
    res_data = call_cmd_resp_call;  //回应命令
    lora_send(device_type, SalveMac, lora_cmd, &res_data, 1);
  } else {
    res_data = call_cmd_resp_del;  //回应命令
    lora_send(device_type, SalveMac, lora_cmd, &res_data, 1);

    disp_delnum();  //显示要删除的分机号码
    set_delnum(1);  //从机确认要删除号码

    voice_value = voice_longpressdel;
    voice.cmd = voicecmd_playone;
    voice.value = (uint8_t *)&voice_value;
    process_start(&VoicePlay_Process, (process_data_t)&voice);
  }
}

void cfg_mac_process(uint8_t device_type, iSMacSn SalveMac, uint8_t *data,
                     uint8_t len) {
  static uint8_t lora_cmd = lora_cmd_cfg;
  static sLEDData set_data;
  static uint8_t flag = 0;
  uint8_t cfg_cmd = data[0];

  if (flag == 0) {
    flag = 1;
    if (netdevice_type == net_device_gsm) {
      exit_gprs();
    } else if (netdevice_type == net_device_wifi) {
      exit_wifi();
    }
    exit_mqtt();
  }

  if (cfg_cmd == cfg_cmd_find) {  //发现命令
    uint8_t res_data[5];
    cfg_cmd = (call_cmd_resp_call | Lora_Cmd_Mask);  //回应命令
    if (cfg_data.Val.MacFlag == Mac_Init) {
      cfg_cmd = cfg_cmd_find_resp_bond;  //回应命令 设备已绑定
    } else {
      cfg_cmd = cfg_cmd_find_resp_nobond;  //回应命令 设备未绑定
    }
    res_data[0] = cfg_cmd;
    res_data[1] = uid.temp2 & 0xff;
    res_data[2] = (uid.temp2 >> 8) & 0xff;
    res_data[3] = (uid.temp2 >> 16) & 0xff;
    res_data[4] = (uid.temp2 >> 24) & 0xff;

    lora_send(device_type, SalveMac, lora_cmd, res_data, 5);

    //启动重发
    resend_cnt = 0;
    ctimer_set(&c_resend, 1 * 1500, resend_callback, NULL);

    set_data.cmd = disp_notwinkle;
    set_data.count = 0xff;
    uint16_t leddata = uid.temp2 & 0xffff;
    set_data.led[3] = NumDis[leddata & 0x000f];
    leddata >>= 4;
    set_data.led[2] = NumDis[leddata & 0x000f];
    leddata >>= 4;
    set_data.led[1] = NumDis[leddata & 0x000f];
    leddata >>= 4;
    set_data.led[0] = NumDis[leddata & 0x000f];
    set_data.led[4] = 0x00;
    process_post(&Disp_Process, PROCESS_EVENT_MSG, (process_data_t)&set_data);
  } else if (cfg_cmd == cfg_cmd_find_comp) {  //发现完成命令
    uint32_t hostmac = data[1] + ((uint32_t)data[2] << 8) +
                       ((uint32_t)data[3] << 16) + ((uint32_t)data[4] << 24);
    if (hostmac == uid.temp2) {
      ctimer_stop(&c_resend);
      resend_cnt = 0;
    }
  } else if (cfg_cmd == cfg_cmd_bond) {
    uint32_t hostmac = data[1] + ((uint32_t)data[2] << 8) +
                       ((uint32_t)data[3] << 16) + ((uint32_t)data[4] << 24);
    uint32_t bondmac = data[5] + ((uint32_t)data[6] << 8) +
                       ((uint32_t)data[7] << 16) + ((uint32_t)data[8] << 24);
    if (hostmac != uid.temp2) {
      return;
    }
    __disable_irq();
    uid.temp0 = cfg_data.Val.Device_mac.Val.temp0 = 0;
    uid.temp1 = cfg_data.Val.Device_mac.Val.temp1 = 0;
    uid.temp2 = cfg_data.Val.Device_mac.Val.temp2 = bondmac;

    cfg_data.Val.MacFlag = Mac_Init;
    cfg_data.Val.DeviceFlag = Device_NotInit;

    __enable_irq();

    uint8_t res_data[5];
    res_data[0] = cfg_cmd_bond_resp;
    res_data[1] = uid.temp2 & 0xff;
    res_data[2] = (uid.temp2 >> 8) & 0xff;
    res_data[3] = (uid.temp2 >> 16) & 0xff;
    res_data[4] = (uid.temp2 >> 24) & 0xff;

    lora_send(device_type, SalveMac, lora_cmd, res_data, 5);
    //启动重发
    resend_cnt = 0;
    ctimer_set(&c_resend, 1 * 1500, resend_callback, NULL);
    //启动保存超时
    ctimer_set(&c_qrcodesave, 10 * 1000, qrcodesave_callback, NULL);

    set_data.cmd = disp_notwinkle;
    set_data.count = 0xff;
    uint16_t leddata = cfg_data.Val.Device_mac.Val.temp2 & 0xffff;
    set_data.led[3] = NumDis[leddata & 0x000f];
    leddata >>= 4;
    set_data.led[2] = NumDis[leddata & 0x000f];
    leddata >>= 4;
    set_data.led[1] = NumDis[leddata & 0x000f];
    leddata >>= 4;
    set_data.led[0] = NumDis[leddata & 0x000f];
    set_data.led[4] = 0x00;
    process_post(&Disp_Process, PROCESS_EVENT_MSG, (process_data_t)&set_data);
  } else if (cfg_cmd == cfg_cmd_bond_comp) {
    uint32_t hostmac = data[1] + ((uint32_t)data[2] << 8) +
                       ((uint32_t)data[3] << 16) + ((uint32_t)data[4] << 24);
    if (hostmac == uid.temp2) {
      write_cfg(&cfg_data);
      ctimer_stop(&c_resend);
      resend_cnt = 0;
      ctimer_stop(&c_qrcodesave);
      process_start(&Reset_Process, NULL);
    }
  }
}

void data_deserialize(uint8_t *buff, uint8_t bufflen) {
  uint8_t head_index = 0;
  uint8_t data_index = 0;
  uint8_t mac_index = 0;
  uint8_t data_len = 0;
  uint8_t mac_len = 0;
  uint8_t cmd = 0;
  uint8_t crc = 0;
  uint8_t data_crc = 0;
  uint8_t *data_prt = NULL;

  if (bufflen < package_min_len) {
    return;
  }

  for (uint8_t i = 0; i < bufflen;) {
    if ((bufflen - i) < package_min_len) {
      return;
    }
    //帧头解析
    if (buff[i++] != Lora_Head) {
      continue;
    }
    head_index = i;
    //类型解析
    device_type = buff[i++];
    // mac解析
    mac_index = i;
    if (device_type == device_st) {
      mac_len = 12;
    } else if ((device_type == device_ble) || (device_type == device_cfg) ||
               (device_type == device_ble_no)) {
      mac_len = 6;
    } else {
      continue;
    }
    i = i + mac_len;
    //命令解析
    cmd = buff[i++];
    //长度解析
    data_len = buff[i++];

    if (data_len > (bufflen - i)) {
      continue;
    }
    data_index = i;

    //校验
    data_crc = buff[i + data_len];
    i++;
    crc = checkxor(&buff[head_index], (data_index + data_len - head_index));
    if (data_crc != crc) {
      continue;
    }
    // mac

    for (uint8_t j = 0; j < mac_len; j++) {
      mac[j] = buff[mac_index + j];
    }
    uSMacSn mac_var;
    if ((device_type == device_ble) || (device_type == device_cfg) || (device_type == device_ble_no)) {
      for (uint8_t j = 0; j < 12; j++) {
        if (j < 6) {
          mac_var.Mac_Var[j] = 0;
        } else {
          mac_var.Mac_Var[j] = mac[j - 6];
        }
      }
    } else {
      for (uint8_t j = 0; j < 12; j++) {
        mac_var.Mac_Var[j] = mac[j];
      }
    }
    SalveMac.temp0 = mac_var.Mac.temp0;
    SalveMac.temp1 = mac_var.Mac.temp1;
    SalveMac.temp2 = mac_var.Mac.temp2;

    //数据
    if (data_len > 0) {
      data_prt = (uint8_t *)malloc(data_len);
    }
    memcpy(data_prt, &buff[data_index], data_len);

    if (cmd == lora_cmd_call_master) {  //分机呼叫命令
      if (cfg_data.Val.MacFlag == Mac_Init) {  //主机添加二维码，才处理呼叫命令
        is_exist = check_flashnum(SalveMac);

        if (netdevice_type != net_device_none) {  //网络版
          model_call_process(device_type, SalveMac, data_prt, data_len);
        } else {  //单机版
          if (Model == Model_Call) {
            model_call_process(device_type, SalveMac, data_prt, data_len);
          } else if (Model == Model_Add) {
            model_add_process(device_type, SalveMac);
          } else if (Model_Del) {
            model_del_process(device_type, SalveMac);
          }
        }
      }
    } else if (cmd == lora_cmd_cfg) {  //设备配置 二维码标识
      if (device_type == device_cfg) {
        cfg_mac_process(device_cfg, SalveMac, data_prt, data_len);
      }
    } else {
    }

    if (data_len > 0) {
      free(data_prt);
    }
  }
}

void rx_done(void) {
  //	static tSend_Data* data;

  Radio->GetRxPacket(Buffer, (uint16_t *)&BufferSize);
#if (1)
  printf("recvdata->len:%d,data:", BufferSize);
  for (uint8_t i = 0; i < BufferSize; i++) {
    printf("%02X", Buffer[i]);
  }
  printf("\r\n");
#endif
  data_deserialize(Buffer, BufferSize);
}

void lora_init() {
  // LORA任务初始化
  Radio = RadioDriverInit();
  Radio->Init();
  Radio->StartRx();

  list_init(callnum_list);
  list_init(callmac_list);
  list_init(sendmac_list);
  memb_maccall_init();
  memb_numcall_init();
}

// LORA数据收发任务

PROCESS_THREAD(LORA_Process, ev, data) {
  static struct etimer et;
  static uint32_t Process_Res;

  PROCESS_BEGIN();

  while (1) {
    etimer_set(&et, 5);
    PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);

    Process_Res = Radio->Process();
    if (Process_Res == RF_RX_TIMEOUT) {
      static uint8_t count = 0;
      count++;
      Radio->GetRxPacket(Buffer, (uint16_t *)&BufferSize);
      if (count == 20) {
        Radio->GetRxPacket(Buffer, (uint16_t *)&BufferSize);
        SX1276LoRaSetOpMode(RFLR_OPMODE_SLEEP);
        etimer_set(&et, 10);
        PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
        SX1276LoRaSetOpMode(RFLR_OPMODE_STANDBY);

        // printf("RF_RX_TIMEOUT\r\n");
        // Radio->SetTxPacket(senddata_buff, 1);
        count = 0;
      }
    } else if (Process_Res == RF_RX_DONE) {
      rx_done();
    } else if (Process_Res == RF_TX_DONE) {
      Radio->StartRx();
    } else {
    }

    Feed_LoraDog();
  }
  PROCESS_END();
}

PROCESS_THREAD(LORASend_Process, ev, data) {
  PROCESS_BEGIN();
  static struct etimer et;

  //  srand(HAL_GetTick());

  etimer_set(&et, (rand() % 10) * 10);
  PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
  Radio->SetTxPacket(senddata_buff, senddata_len);

#if (1)
  printf("senddata->len:%d,data is :", senddata_len);
  for (uint8_t i = 0; i < senddata_len; i++) {
    printf("%02X", senddata_buff[i]);
  }
  printf("\r\n");
#endif

  PROCESS_END();
}

PROCESS_THREAD(Reset_Process, ev, data) {
  PROCESS_BEGIN();
  static struct etimer et;

  etimer_set(&et, 2000);
  PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
  HAL_NVIC_SystemReset();
  PROCESS_END();
}
